﻿using Daphne.Modularity.Messaging;
using Microsoft.Practices.Unity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Daphne.Modularity.Storage;
using Daphne.Modularity.UI;

namespace Daphne.Modularity
{
    /// <summary>
    /// Module instantiating class
    /// </summary>
    public abstract class Bootstrapper
    {
        protected IUnityContainer _unity;
        protected IMessenger _messenger;
        protected IStorageService _storageService;
        protected IRegionManager _regionManager;
        private ModuleCatalog _moduleCatalog;

        /// <summary>
        /// Constructor
        /// </summary>
        public Bootstrapper()
        {
            // init unity container and register itself
            _unity = new UnityContainer();
            _unity.RegisterInstance<IUnityContainer>(_unity);

            // create and register messenger
            _messenger = new Messenger();
            _unity.RegisterInstance<IMessenger>(_messenger);

            // create and register storage service for keeping the state of the application
            _storageService = new StorageService();
            _unity.RegisterInstance<IStorageService>(_storageService);

            // init region manager
            RegionManager.RegisterUnity(_unity);
            _regionManager = new RegionManager();
            _unity.RegisterInstance<IRegionManager>(_regionManager);

            // init module catalog
            _moduleCatalog = new ModuleCatalog();
        }

        /// <summary>
        /// Performs initialization
        /// </summary>
        public void Initialize()
        {
            // configure modules
            ConfigureModule(_moduleCatalog);

            // load modules
            LoadModules();
        }

        /// <summary>
        /// Loads the registered modules
        /// </summary>
        private void LoadModules()
        {
            for (int i = 0; i < _moduleCatalog.Count; i++)
            {
                //  get module type
                Type moduleType = _moduleCatalog[i];

                //  resolve it
                IModule module = _unity.Resolve(moduleType) as IModule;
                if (module == null)
                    throw new InvalidCastException("Module is not of type IModule");

                //  initialize it
                module.Initialize();
            }           
        }

        /// <summary>
        /// Configures the modules
        /// </summary>
        protected abstract void ConfigureModule(ModuleCatalog catalog);
    }
}
